package com.rickpan.storage.performance;

import com.rickpan.storage.monitor.StorageMetricsService;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 存储性能分析和优化建议服务
 * 分析存储操作性能并提供优化建议
 */
@Service
public class StoragePerformanceAnalyzer {
    
    private static final Logger logger = LoggerFactory.getLogger(StoragePerformanceAnalyzer.class);
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    @Autowired
    private StorageMetricsService metricsService;
    
    // 性能阈值配置
    private static final double SLOW_OPERATION_THRESHOLD_MS = 5000; // 5秒
    private static final double HIGH_ERROR_RATE_THRESHOLD = 0.05; // 5%
    private static final long HIGH_ACTIVE_OPERATIONS_THRESHOLD = 50;
    private static final double LOW_THROUGHPUT_THRESHOLD_MBPS = 1.0; // 1 MB/s
    
    /**
     * 生成性能分析报告
     */
    public PerformanceReport generatePerformanceReport() {
        // logger.debug("开始生成存储性能分析报告"); // 开发调试用

        PerformanceReport report = new PerformanceReport();

        // 分析操作性能
        analyzeOperationPerformance(report);

        // 分析错误率
        analyzeErrorRates(report);

        // 分析吞吐量
        analyzeThroughput(report);

        // 分析资源使用
        analyzeResourceUsage(report);

        // 生成优化建议
        generateOptimizationRecommendations(report);

        // 只有在发现问题时才记录详细日志
        if (report.getIssues().size() > 0) {
            logger.info("存储性能分析报告生成完成，发现 {} 个问题，{} 条建议",
                       report.getIssues().size(), report.getRecommendations().size());
        }

        return report;
    }
    
    /**
     * 分析操作性能
     */
    private void analyzeOperationPerformance(PerformanceReport report) {
        try {
            // 获取各种操作的平均响应时间
            Map<String, Double> operationLatencies = new HashMap<>();
            
            // 查询上传操作性能
            Timer uploadTimer = meterRegistry.find("storage.operation.duration")
                .tag("operation", "upload")
                .timer();
            if (uploadTimer != null) {
                double avgLatency = uploadTimer.mean(TimeUnit.MILLISECONDS);
                operationLatencies.put("upload", avgLatency);
                
                if (avgLatency > SLOW_OPERATION_THRESHOLD_MS) {
                    report.addIssue(new PerformanceIssue(
                        "SLOW_UPLOAD",
                        "上传操作响应时间过慢",
                        String.format("平均响应时间: %.2f ms", avgLatency),
                        PerformanceIssue.Severity.WARNING
                    ));
                }
            }
            
            // 查询下载操作性能
            Timer downloadTimer = meterRegistry.find("storage.operation.duration")
                .tag("operation", "download")
                .timer();
            if (downloadTimer != null) {
                double avgLatency = downloadTimer.mean(TimeUnit.MILLISECONDS);
                operationLatencies.put("download", avgLatency);
                
                if (avgLatency > SLOW_OPERATION_THRESHOLD_MS) {
                    report.addIssue(new PerformanceIssue(
                        "SLOW_DOWNLOAD",
                        "下载操作响应时间过慢",
                        String.format("平均响应时间: %.2f ms", avgLatency),
                        PerformanceIssue.Severity.WARNING
                    ));
                }
            }
            
            // 查询URL生成性能
            Timer urlTimer = meterRegistry.find("storage.url.generation.duration")
                .timer();
            if (urlTimer != null) {
                double avgLatency = urlTimer.mean(TimeUnit.MILLISECONDS);
                operationLatencies.put("url_generation", avgLatency);
                
                if (avgLatency > 1000) { // URL生成超过1秒认为过慢
                    report.addIssue(new PerformanceIssue(
                        "SLOW_URL_GENERATION",
                        "URL生成响应时间过慢",
                        String.format("平均响应时间: %.2f ms", avgLatency),
                        PerformanceIssue.Severity.INFO
                    ));
                }
            }
            
            report.setOperationLatencies(operationLatencies);
            
        } catch (Exception e) {
            logger.error("分析操作性能失败", e);
            report.addIssue(new PerformanceIssue(
                "ANALYSIS_ERROR",
                "性能分析失败",
                e.getMessage(),
                PerformanceIssue.Severity.ERROR
            ));
        }
    }
    
    /**
     * 分析错误率
     */
    private void analyzeErrorRates(PerformanceReport report) {
        try {
            Map<String, Double> errorRates = new HashMap<>();
            
            // 分析各种操作的错误率
            String[] operations = {"upload", "download", "delete", "chunk_upload"};
            
            for (String operation : operations) {
                double successCount = getCounterValue("storage.operation.count", 
                    Map.of("operation", operation, "result", "success"));
                double failureCount = getCounterValue("storage.operation.count", 
                    Map.of("operation", operation, "result", "failure"));
                
                if (successCount + failureCount > 0) {
                    double errorRate = failureCount / (successCount + failureCount);
                    errorRates.put(operation, errorRate);
                    
                    if (errorRate > HIGH_ERROR_RATE_THRESHOLD) {
                        report.addIssue(new PerformanceIssue(
                            "HIGH_ERROR_RATE",
                            operation + "操作错误率过高",
                            String.format("错误率: %.2f%%", errorRate * 100),
                            PerformanceIssue.Severity.CRITICAL
                        ));
                    }
                }
            }
            
            report.setErrorRates(errorRates);
            
        } catch (Exception e) {
            logger.error("分析错误率失败", e);
        }
    }
    
    /**
     * 分析吞吐量
     */
    private void analyzeThroughput(PerformanceReport report) {
        try {
            StorageMetricsService.StorageStats stats = metricsService.getStorageStats();
            
            // 计算平均吞吐量（简化计算，实际应该基于时间窗口）
            long totalBytes = stats.getTotalUploadedBytes() + stats.getTotalDownloadedBytes();
            long totalOps = stats.getTotalOperations();
            
            if (totalOps > 0) {
                double avgBytesPerOp = (double) totalBytes / totalOps;
                double avgThroughputMBps = avgBytesPerOp / (1024 * 1024); // 转换为MB
                
                report.setAverageThroughput(avgThroughputMBps);
                
                if (avgThroughputMBps < LOW_THROUGHPUT_THRESHOLD_MBPS) {
                    report.addIssue(new PerformanceIssue(
                        "LOW_THROUGHPUT",
                        "存储吞吐量较低",
                        String.format("平均吞吐量: %.2f MB/操作", avgThroughputMBps),
                        PerformanceIssue.Severity.WARNING
                    ));
                }
            }
            
        } catch (Exception e) {
            logger.error("分析吞吐量失败", e);
        }
    }
    
    /**
     * 分析资源使用
     */
    private void analyzeResourceUsage(PerformanceReport report) {
        try {
            long activeOps = metricsService.getActiveOperationsCount();
            
            if (activeOps > HIGH_ACTIVE_OPERATIONS_THRESHOLD) {
                report.addIssue(new PerformanceIssue(
                    "HIGH_CONCURRENT_OPERATIONS",
                    "并发操作数量过高",
                    String.format("当前活跃操作: %d", activeOps),
                    PerformanceIssue.Severity.WARNING
                ));
            }
            
            report.setActiveOperations(activeOps);
            
        } catch (Exception e) {
            logger.error("分析资源使用失败", e);
        }
    }
    
    /**
     * 生成优化建议
     */
    private void generateOptimizationRecommendations(PerformanceReport report) {
        List<OptimizationRecommendation> recommendations = new ArrayList<>();
        
        // 基于发现的问题生成建议
        for (PerformanceIssue issue : report.getIssues()) {
            switch (issue.getType()) {
                case "SLOW_UPLOAD":
                    recommendations.add(new OptimizationRecommendation(
                        "优化上传性能",
                        "考虑启用分片上传、增加并发数或优化网络配置",
                        OptimizationRecommendation.Priority.HIGH
                    ));
                    break;
                    
                case "SLOW_DOWNLOAD":
                    recommendations.add(new OptimizationRecommendation(
                        "优化下载性能",
                        "考虑启用CDN、增加带宽或优化缓存策略",
                        OptimizationRecommendation.Priority.HIGH
                    ));
                    break;
                    
                case "HIGH_ERROR_RATE":
                    recommendations.add(new OptimizationRecommendation(
                        "降低错误率",
                        "检查网络连接、增加重试机制或优化错误处理",
                        OptimizationRecommendation.Priority.CRITICAL
                    ));
                    break;
                    
                case "LOW_THROUGHPUT":
                    recommendations.add(new OptimizationRecommendation(
                        "提升吞吐量",
                        "考虑增加并发连接数、优化数据传输或升级硬件",
                        OptimizationRecommendation.Priority.MEDIUM
                    ));
                    break;
                    
                case "HIGH_CONCURRENT_OPERATIONS":
                    recommendations.add(new OptimizationRecommendation(
                        "优化并发控制",
                        "考虑实现队列机制、限流或增加资源池大小",
                        OptimizationRecommendation.Priority.MEDIUM
                    ));
                    break;
            }
        }
        
        // 通用优化建议
        if (report.getIssues().isEmpty()) {
            recommendations.add(new OptimizationRecommendation(
                "性能监控",
                "继续监控性能指标，定期分析和优化",
                OptimizationRecommendation.Priority.LOW
            ));
        }
        
        report.setRecommendations(recommendations);
    }
    
    /**
     * 获取计数器值
     */
    private double getCounterValue(String meterName, Map<String, String> tags) {
        try {
            var search = meterRegistry.find(meterName);
            for (Map.Entry<String, String> tag : tags.entrySet()) {
                search = search.tag(tag.getKey(), tag.getValue());
            }
            var counter = search.counter();
            return counter != null ? counter.count() : 0.0;
        } catch (Exception e) {
            logger.warn("获取计数器值失败: {}, tags: {}", meterName, tags, e);
            return 0.0;
        }
    }
    
    /**
     * 性能报告
     */
    public static class PerformanceReport {
        private final List<PerformanceIssue> issues = new ArrayList<>();
        private final List<OptimizationRecommendation> recommendations = new ArrayList<>();
        private Map<String, Double> operationLatencies = new HashMap<>();
        private Map<String, Double> errorRates = new HashMap<>();
        private double averageThroughput;
        private long activeOperations;
        private final long timestamp = System.currentTimeMillis();
        
        public void addIssue(PerformanceIssue issue) { issues.add(issue); }
        public List<PerformanceIssue> getIssues() { return issues; }
        public List<OptimizationRecommendation> getRecommendations() { return recommendations; }
        public void setRecommendations(List<OptimizationRecommendation> recommendations) { 
            this.recommendations.clear();
            this.recommendations.addAll(recommendations);
        }
        public Map<String, Double> getOperationLatencies() { return operationLatencies; }
        public void setOperationLatencies(Map<String, Double> operationLatencies) { this.operationLatencies = operationLatencies; }
        public Map<String, Double> getErrorRates() { return errorRates; }
        public void setErrorRates(Map<String, Double> errorRates) { this.errorRates = errorRates; }
        public double getAverageThroughput() { return averageThroughput; }
        public void setAverageThroughput(double averageThroughput) { this.averageThroughput = averageThroughput; }
        public long getActiveOperations() { return activeOperations; }
        public void setActiveOperations(long activeOperations) { this.activeOperations = activeOperations; }
        public long getTimestamp() { return timestamp; }
    }
    
    /**
     * 性能问题
     */
    public static class PerformanceIssue {
        public enum Severity { INFO, WARNING, CRITICAL, ERROR }
        
        private final String type;
        private final String title;
        private final String description;
        private final Severity severity;
        
        public PerformanceIssue(String type, String title, String description, Severity severity) {
            this.type = type;
            this.title = title;
            this.description = description;
            this.severity = severity;
        }
        
        public String getType() { return type; }
        public String getTitle() { return title; }
        public String getDescription() { return description; }
        public Severity getSeverity() { return severity; }
    }
    
    /**
     * 优化建议
     */
    public static class OptimizationRecommendation {
        public enum Priority { LOW, MEDIUM, HIGH, CRITICAL }
        
        private final String title;
        private final String description;
        private final Priority priority;
        
        public OptimizationRecommendation(String title, String description, Priority priority) {
            this.title = title;
            this.description = description;
            this.priority = priority;
        }
        
        public String getTitle() { return title; }
        public String getDescription() { return description; }
        public Priority getPriority() { return priority; }
    }
}
